/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "面/Surface.h"
#include "面/面.h"
#include "数学/数学.h"
#include "core/几何计算/多边形.h"

#include "底层绘图/intern/Vulkan/Vulkan框架.h"

#include <core/时间.h>
#include <系统/多线程.h>

#include <ft2build.h>
#include FT_FREETYPE_H
#include <freetype.h>


// 二次贝塞尔曲线插值
Inline vec2 quadratic_bezier(const vec2& p0, const vec2& p1, const vec2& p2, float t) {
	float u = 1 - t;
	return vec2{ u * u * p0.x + 2 * u * t * p1.x + t * t * p2.x,
				u * u * p0.y + 2 * u * t * p1.y + t * t * p2.y
				};
}

// 三次贝塞尔曲线插值
Inline vec2 cubic_bezier(const vec2& p0, const vec2& p1, const vec2& p2, const vec2& p3, float t) {
	float u = 1 - t;
	return vec2{ u * u * u * p0.x + 3 * u * u * t * p1.x + 3 * u * t * t * p2.x + t * t * t * p3.x,
				u * u * u * p0.y + 3 * u * u * t * p1.y + 3 * u * t * t * p2.y + t * t * t * p3.y
				};
}





// 处理轮廓的回调函数数据
typedef struct {
	PolygonData* data;
	std::vector<uint32_t> current_edge;
} CallbackData;




// 处理轮廓
static void process_outline(const FT_Outline* outline, PolygonData& polygon_data) {
	std::vector<uint32_t> current_edge;
	auto tag = outline->tags;

	bool first_point = true;
	float last_on_x = 0, last_on_y = 0;
	const int steps = 8;
	

	for (int32 圈ID = 0; 圈ID < outline->n_contours; ++圈ID) {
		std::vector<uint32_t> contour;
		int start = (圈ID == 0) ? 0 : outline->contours[圈ID - 1] + 1;
		int end = outline->contours[圈ID];

		vec2 curve[16];
		int32 typeOffset = 0;
		bool 结尾曲线插值 = false;
		

		for (int j = start; j <= end; ++j) {
			const FT_Vector& p = outline->points[j];
			const bool is_on = (outline->tags[j] & FT_CURVE_TAG_ON);
			const vec2 p0 = _Vec2(p.x / 128.f, p.y / 128.f);
			

			curve[typeOffset] = p0;
			++typeOffset;
			

			if (tag[j] & FT_CURVE_TAG_ON == FT_CURVE_TAG_ON) {
				switch (typeOffset) {
					case 0:
					case 1: {
						break;
					}
					case 2: {
						current_edge.emplace_back(polygon_data.point.size());
						polygon_data.point.push_back(curve[0]);
						current_edge.emplace_back(polygon_data.point.size());
						polygon_data.point.push_back(curve[1]);

						curve[0] = p0;
						typeOffset = 1;
						结尾曲线插值 = true;
						break;
					}
					case 3: {
						for (int k = 0; k <= steps; ++k) {
							float t = (float)k / steps;
							vec2 point = quadratic_bezier(curve[0], curve[1], curve[2], t);
							current_edge.emplace_back(polygon_data.point.size());
							polygon_data.point.push_back(point);
						}
						curve[0] = p0;
						typeOffset = 1;
						结尾曲线插值 = true;
						break;
					}
					case 4: {
						for (int k = 0; k <= steps; ++k) {
							float t = (float)k / steps;
							//vec2 point = cubic_bezier(curve[0], curve[1], curve[2], curve[3], t);
							vec2 point = f_cubicCurve_sample(curve[0], curve[1], curve[2], curve[3], t);
							current_edge.emplace_back(polygon_data.point.size());
							polygon_data.point.push_back(point);
						}
						curve[0] = p0;
						typeOffset = 1;
						结尾曲线插值 = true;
						break;
					}
					default: {
						for (int32 i = 0; i < typeOffset; ) {
							if (i + 3 < typeOffset) {
								for (int k = 1; k < steps; ++k) {
									float t = (float)k / steps;
									//vec2 point = cubic_bezier(curve[i], curve[i+1], curve[i+2], curve[i+3], t);
									vec2 point = f_cubicCurve_sample(curve[i], curve[i+1], curve[i+2], curve[i+3], t);
									current_edge.emplace_back(polygon_data.point.size());
									polygon_data.point.push_back(point);
								}
								i += 3;
							}
							else if (i + 2 < typeOffset) {
								for (int k = 1; k < steps; ++k) {
									float t = (float)k / steps;
									vec2 point = quadratic_bezier(curve[i], curve[i+1], curve[i+2], t);
									current_edge.emplace_back(polygon_data.point.size());
									polygon_data.point.push_back(point);
								}
								i += 2;
							}
							else {
								break;
							}
							//break;
						}

						curve[0] = p0;
						typeOffset = 1;
						结尾曲线插值 = true;
						
						break;
					}
						
				}
			}
			else {
				结尾曲线插值 = false;
			}
			//std::cout<<"tag[j] "<<tag[j]<<"\n";
			//std::cout<<"tag:"<< int32(tag[j]) << " j:"<<j<< " i:" << 圈ID << "\n";
		}


		if (tag[end]) {
			//const FT_Vector& p0 = outline->points[end];
			//const FT_Vector& p1 = outline->points[start];
			//curve[0] = _Vec2(p0.x / 128.f, p0.y / 128.f) * vec2{1,-1};
			//curve[1] = _Vec2(p1.x / 128.f, p1.y / 128.f) * vec2{1,-1};
			//
			//current_edge.emplace_back(polygon_data.point.size());
			//polygon_data.point.push_back(curve[0]);
			//current_edge.emplace_back(polygon_data.point.size());
			//polygon_data.point.push_back(curve[1]);
		}
		else {
			const FT_Vector& p0 = outline->points[end - 2];
			const FT_Vector& p1 = outline->points[end - 1];
			const FT_Vector& p2 = outline->points[end];
			const FT_Vector& p3 = outline->points[start];
		
		
			curve[0] = _Vec2(p0.x / 128.f, p0.y / 128.f);
			curve[1] = _Vec2(p1.x / 128.f, p1.y / 128.f);
			curve[2] = _Vec2(p2.x / 128.f, p2.y / 128.f);
			curve[3] = _Vec2(p3.x / 128.f, p3.y / 128.f);
			for (int k = 1; k < steps; ++k) {
				float t = (float)k / steps;
		
				if (typeOffset >= 3) {
					//vec2 point = cubic_bezier(curve[0], curve[1], curve[2], curve[3], t);
					vec2 point = f_cubicCurve_sample(curve[0], curve[1], curve[2], curve[3], t);
					current_edge.emplace_back(polygon_data.point.size());
					polygon_data.point.push_back(point);
				}
				else {
					vec2 point = quadratic_bezier(curve[1], curve[2], curve[3], t);
					current_edge.emplace_back(polygon_data.point.size());
					polygon_data.point.push_back(point);
				}
			}
		
		}
		//if(current_edge.size()) current_edge.emplace_back(current_edge.front());


		if(current_edge.size()) {
			polygon_data.edges.push_back(current_edge);
			current_edge.clear();
		}
	}
}

bool f_surface_加载矢量字体(S_设备环境& ctx, const S_字体加载参数& 字体参数, std::u16string name) {
	auto* rf = f_vk_get绘图框架(ctx);
	if(rf->m_字体.find(name) != rf->m_字体.end()) return false;

	std::cout<<" **************** 开始加载字体 ********************\r";
	C_计时 计时("加载字体");

	FT_Library library;
	FT_Face face;
	FT_GlyphSlot slot;
	FT_Error error;
	FT_Outline_Funcs callbacks;


	error = FT_Init_FreeType(&library);
	if (error) {
		fprintf(stderr, "Could not initialize FreeType library\n");
		return false;
	}

	// 加载字体文件
	error = FT_New_Face(library, 字体参数.m_字体文件路径.c_str(), 0, &face);
	if (error == FT_Err_Unknown_File_Format) {
		fprintf(stderr, "The font file could not be opened or read, or is unsupported\n");
		FT_Done_FreeType(library);
		return false;
	} 
	else if (error) {
		fprintf(stderr, "The font file could not be opened or read\n");
		FT_Done_FreeType(library);
		return false;
	}

	// 加载字体文件
	error = FT_Select_Charmap(face, FT_ENCODING_UNICODE);

	// 设置字体大小
	error = FT_Set_Char_Size(face, 0, 1, 96, 96);
	if (error) {
		fprintf(stderr, "Could not set font size\n");
		FT_Done_Face(face);
		FT_Done_FreeType(library);
		return 1;
	}

	face->charmap->encoding;

	S_矢量字体 字体;

	
	
	//std::vector<PolygonData> polygon_data(65536);
	std::vector<S_2D路径层>				polygon_2D路径(65536);
	std::vector<std::vector<uint32_t>>	polygon_三角形(65536);
	字体.m_字符属性.resize(65536);


	
	

	

	uint32 字型数量 = 65536;
#ifdef _DEBUG
	字型数量 = 6553;
#endif // DEBUG


	// 获取字符的字形索引
	for (uint32 i = 0; i < 字型数量; ++i) {
		bool 有字形 = true;
		FT_UInt glyph_index = FT_Get_Char_Index(face, i);
		if (glyph_index == 0) {
			有字形 = false;
			//continue;
		}

		// 加载字形
		error = FT_Load_Glyph(face, glyph_index, //FT_LOAD_DEFAULT 
												//FT_LOAD_NO_SCALE | 
												FT_LOAD_NO_BITMAP | 
												//FT_LOAD_NO_AUTOHINT |
												//FT_LOAD_TARGET_NORMAL  |
												FT_LOAD_NO_HINTING   //|
												//FT_LOAD_NO_RECURSE
												);
		if (error) {
			fprintf(stderr, "Could not load glyph for char code %lu\n", '0');
			有字形 = false;
			//continue;
		}


		slot = face->glyph;
		// 检查是否有轮廓
		if (slot->format != FT_GLYPH_FORMAT_OUTLINE) {
			有字形 = false;
			//continue;
		}

		if (有字形) {
			PolygonData polygon_data;
			// 遍历轮廓
			process_outline(&slot->outline, polygon_data);
			polygon_2D路径[i] = f_polygon_构建2D路径(polygon_data.point, polygon_data.edges);

			字体.m_字符属性[i].width = slot->metrics.width;
			字体.m_字符属性[i].height = slot->metrics.height;
			字体.m_字符属性[i].horiBearingX = slot->metrics.horiBearingX;
			字体.m_字符属性[i].horiBearingY = slot->metrics.horiBearingY;
			字体.m_字符属性[i].horiAdvance = slot->metrics.horiAdvance;
			字体.m_字符属性[i].vertBearingX = slot->metrics.vertBearingX;
			字体.m_字符属性[i].vertBearingY = slot->metrics.vertBearingY;
			字体.m_字符属性[i].vertAdvance = slot->metrics.vertAdvance;
		}
		else {
			字体.m_字符属性[i].width = 1;
			字体.m_字符属性[i].height = 1;
			字体.m_字符属性[i].horiBearingX = 1;
			字体.m_字符属性[i].horiBearingY = 1;
			字体.m_字符属性[i].horiAdvance = 1;
			字体.m_字符属性[i].vertBearingX = 1;
			字体.m_字符属性[i].vertBearingY = 1;
			字体.m_字符属性[i].vertAdvance = 1;
		}
	}
	
	

	
	omp_set_num_threads(8);
#pragma omp parallel for
	for (int32 i = 0; i < 65536; ++i) {
		if (polygon_2D路径[i].point.size()) {
			polygon_三角形[i] = f_polygon_从链表构建三角形(polygon_2D路径[i]);

			
			auto bound = f_geom_Bound(polygon_2D路径[i].point.size(), polygon_2D路径[i].point.data());

			字体.m_字符属性[i].horiBearingX = bound.max.x - bound.min.x;
			字体.m_字符属性[i].horiBearingY = bound.max.y - bound.min.y;
			
		}
		else {
			switch (i) {
				case ' ': {
					字体.m_字符属性[i].horiBearingX = 0.3;
					字体.m_字符属性[i].horiBearingY = 0.3;
					break;
				}
				case '\t': {
					字体.m_字符属性[i].horiBearingX = 1;
					字体.m_字符属性[i].horiBearingY = 0.3;
					break;
				}
				default: {

					break;
				}
			}
		}
	}
	
	

	uint32 坐标起始索引 = 0;
	std::vector<mat2>   文字顶点;
	std::vector<uint32> 文字边索引;
	std::vector<uint32> 文字顶点索引;

	for (uint32 i = 0; i < 65536; ++i) {
		if (polygon_三角形[i].size()) {
			uint32 当前文字轮廓开始索引 = 文字边索引.size();
			uint32 当前文字轮廓线段数量 = 0;
			for (auto& e : polygon_2D路径[i].index) {
				int32 索引数量 = max(0, int32(e.size()) - 1);
	
				auto it = e.begin();
				for (uint32 v = 0; v < 索引数量; ++v) {
					文字边索引.emplace_back(坐标起始索引 + it->p);
					文字边索引.emplace_back(坐标起始索引 + std::next(it)->p);
					++it;
				}
				if (索引数量) {
					当前文字轮廓线段数量 += 索引数量 * 2;
				}
			}
			字体.m_矢量文字边索引区间.push_back(_uVec2(当前文字轮廓开始索引, 当前文字轮廓线段数量));
	
			polygon_三角形[i] += 坐标起始索引;
			for (auto& e :polygon_2D路径[i].point) {
				文字顶点.push_back({{e.x, 0.5f + e.y * -1}, {1,1}});
			}
			坐标起始索引 = 文字顶点.size();
	
			字体.m_矢量文字索引区间.emplace_back(_uVec2(文字顶点索引.size(), polygon_三角形[i].size()));
			文字顶点索引.insert(文字顶点索引.end(), polygon_三角形[i].begin(), polygon_三角形[i].end());
		}
		else {
			字体.m_矢量文字索引区间.emplace_back(_uVec2(0));
			字体.m_矢量文字边索引区间.emplace_back(_uVec2(0));
		}
	}


	字体.m_矢量文字顶点 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_顶点, 0);
	字体.m_矢量文字索引 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_索引, 0);
	字体.m_矢量文字轮廓索引 = f_bm_alloc(ctx.m_几何图形->m_平面图形GPU缓存_索引, 0);

	//f_bm_push_back(字体.m_矢量文字顶点, 文字顶点.data(), 文字顶点.size());
	f_bm_fill(字体.m_矢量文字顶点, 文字顶点.data(), 文字顶点.size());
	uint32 offset = 字体.m_矢量文字顶点.m_Mem.m_偏移;


	文字边索引 += offset;
	//f_bm_push_back(字体.m_矢量文字轮廓索引, 文字边索引.data(), 文字边索引.size());
	f_bm_fill(字体.m_矢量文字轮廓索引, 文字边索引.data(), 文字边索引.size());

	文字顶点索引 += offset;
	//f_bm_push_back(字体.m_矢量文字索引, 文字顶点索引.data(), 文字顶点索引.size());
	f_bm_fill(字体.m_矢量文字索引, 文字顶点索引.data(), 文字顶点索引.size());

	offset = 字体.m_矢量文字轮廓索引.m_Mem.m_偏移;
	for (auto& e : 字体.m_矢量文字边索引区间) {
		e.x += offset;
	}

	offset = 字体.m_矢量文字索引.m_Mem.m_偏移;
	for (auto& e : 字体.m_矢量文字索引区间) {
		e.x += offset;
	}

	rf->m_字体[name] = 字体;

	vec2 p1 = (_Vec2(-0.005, 2.01 * 10)*0);
	vec2 p2 = (_Vec2(2.005 * 1, 10.01));
	vec2 p3 = (_Vec2(0.006 * 10, -10.101));
	float32 a = cross(p1, p2, p3);
	
	vec2 p4 = {-0.01, 0.01};
	float32 b = cross(p1, p4, p3);

	// 清理资源
	FT_Done_Face(face);
	FT_Done_FreeType(library);


	计时.end();

	//DEF_记录日志("构建渲染环境");

	return true;
}

bool f_surface_卸载矢量字体(S_设备环境& ctx, std::u16string name) {
	auto* rf = f_vk_get绘图框架(ctx);
	if(rf->m_字体.find(name) == rf->m_字体.end()) {
		return false;
	}

	auto& 字体 = rf->m_字体[name];

	f_bm_erase(字体.m_矢量文字顶点);
	f_bm_erase(字体.m_矢量文字索引);
	
	rf->m_字体.erase(name);
	return true;
}



void f_surface_get矢量字符网格(S_设备环境& ctx, uint16 字符, std::u16string 字体, S_Mesh* me) {
	auto* rf = f_vk_get绘图框架(ctx);

	if(rf->m_字体.find(字体) == rf->m_字体.end()) {
		const auto& font = rf->m_字体[字体];

		auto range = font.m_矢量文字索引区间[字符];
		auto vert = f_bm_ptr<mat2>(font.m_矢量文字顶点);
		auto index = f_bm_ptr<uint32>(font.m_矢量文字索引);

		std::map<uint32 , uint32> 索引重映射;

		std::vector<S_VNTC> 新顶点;
		std::vector<uint32> 新索引;
		for (uint32 i = range.x; i < range.y; ++i) {
			uint32 索引 = index[i];

			if (索引重映射.find(索引) != 索引重映射.end()) {
				索引 = 索引重映射[索引];
			}
			else {
				索引重映射[索引] = i;
				索引 = i;

				新顶点.push_back({_Vec3(vert[索引].m0), {0,0,1}, {0,0,0} });
			}

			新索引.emplace_back(索引);
		}

		f_me_fill顶点(me, 新顶点);
		uint32 offset = me->m_顶点->m_Mem.m_偏移;
		新索引 += offset;
		f_me_fill索引(me, 新索引);
	}

}





void f_surface_字体行文本排版(S_VkDrawIndexedIndirectCommand* indirect, mat3* mat, uint* color, 
								const std::u16string& text, const S_Rect2Df& rect, const S_RGBA8UI& 颜色, 
								const uvec2* 索引, S_字体字符属性* 字符属性) {

	uint32 num = text.size();
	uint32 颜色包 = f_PackData4X8(颜色);

	float32 步进 = 0;
	for (uint32 i = 0; i < num; ++i) {
		auto r = 索引[text[i]];

		indirect[i].firstInstance = 0;
		indirect[i].instanceCount = 1;

		indirect[i].firstIndex = r.x;
		indirect[i].indexCount = r.y;

		indirect[i].vertexOffset = 0;

		mat[i] = f_math_tranform({ 步进, float32(字符属性[i].horiBearingY) }, rect.extent);
		步进 += 字符属性[i].horiBearingX;

		color[i] = 颜色包;
	}
}



